home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / GRAHAM / XA_6S.ZIP / SOURCE / HANDLER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-30  |  8.0 KB  |  285 lines

  1. /*
  2.  * XaAES - XaAES Ain't the AES
  3.  *
  4.  * A multitasking AES replacement for MiNT
  5.  *
  6.  */
  7.  
  8. /*
  9.     Main AES trap handler routine
  10.     -----------------------------
  11.     This module replaces the AES trap 2 vector to provide an interface to the
  12.     XaAES pipe based client/server AES, for normal GEM applications.
  13.     
  14.     It works by first creating a pair of XaAES reply pipes for the application
  15.     in response to the appl_init() call, then using these to communicate with the
  16.     AES server kernal. When an AES trap occurs, the handler drops the pointer to the
  17.     parameter block into the XaAES.cmd pipe.
  18.     
  19.     There are then 3 modes that the AES could have been called in.
  20.     
  21.     If standard GEM emulation mode the handler then drops back into user mode and
  22.     blocks whilst reading on the current process's reply pipe. This allows other
  23.     processes to execute whilst XaAES is performing AES functions (the XaAES server
  24.     runs wholely in user mode so it's more MiNT-friendly than MultiTOS). The server
  25.     writes back to the clients reply pipe with the reply when it has serviced
  26.     the command - this unblocks the client which then returns from the exception.
  27.     
  28.     If NOREPLY mode is used, the AES doesn't block the calling process to wait
  29.     for a reply - and indeed, won't generate one.
  30.     
  31.     If NOBLOCK mode is used, the AES doesn't block the calling process - but does
  32.     place the results in the client's reply pipe. The client is then expected to
  33.     handle it's own reply pipe. This allows multiple AES calls to be made without
  34.     blocking a process, so an app could make all it's GEM initialisation calls
  35.     at one go, then go on to do it's internal initialisation before coming back
  36.     to see if the AES has serviced it's requests (less blocking in the client,
  37.     and better multitasking).
  38.  
  39.     [13/2/96]
  40.     Included Martin Koehling's patches - this nicely does away with the 'far' data
  41.     kludges & register patches I had in before.....
  42.  
  43.     [18/2/96]
  44.     New timeout stuff to replace the SIGALRM stuff.
  45. */
  46.  
  47.  
  48. #include <OSBIND.H>
  49. #include <MINTBIND.H>
  50. #include <FILESYS.H>
  51. #include <stdio.h>
  52. #include "K_DEFS.H"
  53. #include "HANDLER.H"
  54. #include "XA_DEFS.H"
  55. #include "XA_GLOBL.H"
  56. #include "frm_alrt.h"
  57. #include "XA_CODES.H"
  58. #include "appl_ini.h"
  59. #include "KERNAL.H"
  60.  
  61. __regargs short handler(unsigned short c, AESPB *pb);
  62.  
  63. #define AES_MAGIC            12345
  64.  
  65. static K_CMD_PACKET client_request;
  66.  
  67. /*
  68.     Trap exception handler - this routine executes under the client applications pid
  69.     - I've semaphore locked any sensitive bits
  70.  
  71.     NOTE: the keyword `__saveds' causes the compiler to load the global base
  72.     register automatically - no need for `far' data kludges here!!!
  73. */
  74. far __saveds __regargs short XA_handler(unsigned short c, AESPB *pb)
  75. {
  76.     short clnt_pid=Pgetpid();
  77.     XA_CLIENT *client;
  78.     unsigned long cmd_rtn;
  79.     short rtn_mode;
  80.     unsigned long reply_s;
  81.     short timeout;
  82.     
  83.     client=Pid2Client(clnt_pid);    
  84.  
  85.     if (Kcall_direct[pb->contrl[0]])    /* Call direct? */
  86.     {
  87.  
  88.         if ((pb->contrl[0]>=0)&&(pb->contrl[0]<300))
  89.         {
  90.             AESroutine cmd_routine=Ktable[pb->contrl[0]];
  91.  
  92.             if (cmd_routine)        /* If opcode was implemented, call it */
  93.             {
  94.                 cmd_rtn=(*cmd_routine)(clnt_pid,pb);
  95.                 rtn_mode=cmd_rtn&0xf;
  96.                 
  97.                 switch(rtn_mode)
  98.                 {
  99.                     case XAC_BLOCK:        /* Block indefinitely (like for evnt_mesag) */
  100.                         Fread(client->clnt_pipe_rd,sizeof(unsigned long),&cmd_rtn);
  101.                         break;
  102.                     case XAC_T_TIMEOUT:    /* Block, with a timeout (evnt_timer format)*/
  103.                     case XAC_M_TIMEOUT:    /* Block, with a timeout (evnt_multi format)*/
  104.                         reply_s=1L<<client->clnt_pipe_rd;
  105.                         timeout=(cmd_rtn&XAC_TVAL)>>16;
  106.                         
  107.                         if (!timeout)
  108.                             timeout=1;
  109.                             
  110.                         cmd_rtn=Fselect(timeout,(long *)&reply_s,NULL,NULL);
  111.  
  112.                         Psemaphore(2,CLIENTS_SEMAPHORE,-1L);
  113.                         
  114.                         if (!cmd_rtn)    /* timed out */
  115.                         {    
  116.                             if(client->waiting_for&XAWAIT_MULTI)
  117.                             {
  118.                                 client->waiting_pb->intout[0]=MU_TIMER;    /* evnt_multi() returns MU_TIMER */
  119.                             }else{
  120.                                 client->waiting_pb->intout[0]=1;    /* evnt_timer() always returns 1 */
  121.                             }
  122.                             client->waiting_for=0;
  123.                         }
  124.                         
  125.                         Psemaphore(3,CLIENTS_SEMAPHORE,0L);
  126.  
  127.                         break;
  128.                     case XAC_DONE:        /* Command completed, do nothing & return */
  129.                         break;
  130.                 }
  131.             }else{
  132.                 pb->intout[0]=0;
  133.             }
  134.         }
  135.  
  136.     }else{        /* Nope, go through the pipes messaging system instead... */
  137.  
  138.         Psemaphore(2,TRAP_HANDLER_SEMAPHORE,-1L);
  139.  
  140.         client_request.pid=clnt_pid;    /* Build command packet */
  141.         client_request.cmd=c;
  142.         client_request.pb=pb;
  143.  
  144.         Fwrite(client->clnt_pipe_rd, (long)sizeof(K_CMD_PACKET), &client_request);    /* Send command packet */
  145.  
  146.         Psemaphore(3,TRAP_HANDLER_SEMAPHORE,0);
  147.  
  148.         if (c!=AESCMD_STD)                 /* Unless we are doing standard GEM style AES calls, return  */
  149.             return client->clnt_pipe_rd;    /* here. */
  150.  
  151. /* OK, here we are in blocking AES call mode (standard GEM) - so we handle the reply pipe */
  152. /* on behalf of the client. */
  153.  
  154.         Fread(client->clnt_pipe_rd,sizeof(unsigned long),&cmd_rtn);
  155.         
  156.         timeout=cmd_rtn>>16;
  157.         rtn_mode=cmd_rtn&0xf;
  158.         
  159.         switch(rtn_mode)    /* New timeout stuff */
  160.         {
  161.             case XA_OK:            /* Standard stuff, operation completed, etc */
  162.             case XA_ILLEGAL:
  163.             case XA_UNIMPLEMENTED:
  164.                 break;
  165.             case XA_T_WAIT:        /* Ahh - block again, with a timeout */
  166.             case XA_M_WAIT:
  167.                 {
  168.  
  169.                     reply_s=1L<<client->clnt_pipe_rd;
  170.                     
  171.                     if (!timeout)
  172.                         timeout=1;
  173.                     
  174.                     cmd_rtn=Fselect(timeout,(long *)&reply_s,NULL,NULL);
  175.                     
  176.                     Psemaphore(2,CLIENTS_SEMAPHORE,-1L);
  177.  
  178.                     if (!cmd_rtn)    /* timed out */
  179.                     {
  180.                         if (client->waiting_for&XAWAIT_MULTI)
  181.                         {
  182.                             client->waiting_pb->intout[0]=MU_TIMER;    /* evnt_multi() returns MU_TIMER */
  183.                         }else{
  184.                             client->waiting_pb->intout[0]=1;    /* evnt_timer() always returns 1 */
  185.                         }
  186.                         
  187.                         client->waiting_for=0;
  188.                         
  189.                     }else{    /* Second dummy read to unblock */
  190.                         Fread(client->clnt_pipe_rd,sizeof(unsigned long),&cmd_rtn);
  191.                     }
  192.                     
  193.                     Psemaphore(3,CLIENTS_SEMAPHORE,0L);
  194.  
  195.                 }
  196.                 break;
  197.         }
  198.     }
  199.     
  200.     return AES_MAGIC;
  201. }
  202.  
  203. extern void asm_hook_into_vector(void);
  204.  
  205. void hook_into_vector(void)
  206. {
  207.     void *old_ssp;
  208.  
  209.     old_ssp=(void *)Super((void*)NULL);        /* Enter Supervisor mode*/
  210.     
  211.     asm_hook_into_vector();
  212.     
  213.     /* We want to do this with task switching disabled in order
  214.         to prevent a possible race condition... */
  215.     /* Dummy access to the critical error handler (make Selectric,
  216.         FSELECT and other AES extenders happy...) */
  217.     (void)Setexc(0x101, (void*)-1L);
  218.     Super(old_ssp);                    /* Back to User Mode */
  219. }
  220.  
  221. #if 0
  222. extern void * far old_trap2_vector; /* defined in a_handler.s (TEXT segment!) */
  223. /*
  224.     HOOK INTO THE AES TRAP VECTOR
  225.     - new version [13/2/96] by Martin Koehling.
  226. */
  227. void hook_into_vector(void)
  228. {
  229.     void *old_ssp;
  230.  
  231. #if 0
  232.     printf("- XaAES hooking into trap vector %d at location %lx\n",
  233.             AES_TRAP, (0x20+AES_TRAP)*4L);
  234. #endif
  235.  
  236.     old_ssp=(void *)Super((void*)NULL);        /* Enter Supervisor mode*/
  237.     /* We want to do this with task switching disabled in order
  238.         to prevent a possible race condition... */
  239.     old_trap2_vector = Setexc(0x20+AES_TRAP, (void*)handler) ;
  240.     /* Dummy access to the critical error handler (make Selectric,
  241.         FSELECT and other AES extenders happy...) */
  242.     (void)Setexc(0x101, (void*)-1L);
  243.     Super(old_ssp);                    /* Back to User Mode */
  244. }
  245. #endif
  246.  
  247. typedef struct xbra {
  248.     long xbra_id;
  249.     long app_id;
  250.     void (*oldvec)();
  251. } XBRA;
  252.  
  253. /* New unhook, pays attention to XBRA unhook procedure */
  254. void unhook_from_vector(void)
  255. {
  256.     void *old_ssp;
  257.     XBRA *rx;
  258.     long vecadr, *stepadr;
  259.  
  260.      vecadr=(long)Setexc(0x20+AES_TRAP,(void*)-1L);     
  261.      rx=(XBRA*)(vecadr-sizeof(XBRA));
  262.  
  263.     old_ssp=(void*)Super((void*)NULL);
  264.  
  265.     if ((rx->xbra_id=='XBRA')&&(rx->app_id=='XaAE'))
  266.     {
  267.         Setexc(0x20+AES_TRAP, rx->oldvec);
  268.         return;
  269.     }
  270.     
  271.     stepadr=(long*)&rx->oldvec;
  272.     rx=(XBRA*)((long)rx->oldvec - sizeof(XBRA));
  273.     while(rx->xbra_id=='XBRA')
  274.     {
  275.         if (rx->app_id=='XaAE')
  276.         {
  277.             *stepadr=(long)rx->oldvec;
  278.             break;
  279.         }
  280.         stepadr=(long*)&rx->oldvec;
  281.         rx=(XBRA*)((long)rx->oldvec - sizeof(XBRA));
  282.     }
  283.     Super(old_ssp);
  284. }
  285.